
/*
 * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
 *
 * (b)  If this Sample Code is distributed as part of the Display PostScript
 *	System Software Development Kit from Adobe Systems Incorporated,
 *	then this copy is designated as Development Software and its use is
 *	subject to the terms of the License Agreement attached to such Kit.
 *
 * (c)  If this Sample Code is distributed independently, then the following
 *	terms apply:
 *
 * (d)  This file may be freely copied and redistributed as long as:
 *	1) Parts (a), (d), (e) and (f) continue to be included in the file,
 *	2) If the file has been modified in any way, a notice of such
 *      modification is conspicuously indicated.
 *
 * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
 *	Adobe Systems Incorporated.
 * 
 * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
 *	CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
 *	AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
 *	ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
 *	OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
 *	WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
 *	WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
 *	DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
 *	FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
 *	OF THIRD PARTY RIGHTS.
 */

/*
 *	Graphic.m
 *
 *	Version:	2.0
 *	Author:	Ken Fromm
 *	History:
 *			03-07-91		Added this comment.
 */

#import "Graphic.h"
#import "DrawingViewWraps.h"
#import <appkit/defaults.h>
#import <appkit/nextstd.h>
#import <dpsclient/wraps.h>

extern void makeRedBook(UPath *aUpath);

void initGparms(GParms *gParms)
{
	gParms->path_type = STROKE;
	gParms->color =  NX_COLORBLACK;
	gParms->linewidth = 1;
	gParms->miterlimit = 10;
	gParms->linejoin = gParms->linecap = 0;
}

void setGparms(GParms *gParms)
{
	PSWSetParameters((int)gParms->linejoin, (int) gParms->linecap,
			gParms->linewidth, gParms->miterlimit);
}

@implementation Graphic : Object

+ new
{
	self = [super new];
	initGparms(&parms);
    
	return self;
}

- free
{
	if (path.pts)
		NX_FREE(path.pts);
	if (path.ops)
		NX_FREE(path.ops);

	return self;
}

- installGparms:(const GParms *) gParm
{
	parms = *gParm;

	return self;
}

- installUpath:(const UPath *) aUpath andBounds:(const NXRect *) aRect
{
	NX_MALLOC(path.pts, float, aUpath->num_pts+4);
	NX_MALLOC(path.ops, char, aUpath->num_ops+1);

	bcopy(aUpath->pts, &path.pts[4], aUpath->num_pts * sizeof(float)/sizeof(char));
	path.num_pts = aUpath->num_pts + 4;

	path.ops[0] = dps_ucache;
	bcopy(aUpath->ops, &path.ops[1], aUpath->num_ops);
	path.num_ops = aUpath->num_ops + 1;


	bounds = *aRect;
	path.pts[0] = bounds.origin.x;
	path.pts[1] = bounds.origin.y;
	path.pts[2] = bounds.origin.x + bounds.size.width;
	path.pts[3] = bounds.origin.y + bounds.size.height;

	return self;
}

- getBounds:(NXRect *)theRect
{
	*theRect = bounds;

	return self;
}

/* Private methods sometimes overridden by subclassers */
- setPSState:(GParms *) gParms
{
	if (!gParms)
		setGparms(&parms);
	else
	{
		if (parms.linewidth != gParms->linewidth)
			PSsetlinewidth(parms.linewidth);
		if (parms.linejoin != gParms->linejoin)
			PSsetlinejoin((int) parms.linejoin);
		if (parms.linecap != gParms->linecap)
			PSsetlinecap((int) parms.linecap);
		if (parms.miterlimit != gParms->miterlimit)
			PSsetmiterlimit(parms.miterlimit);
	}

	if (!gParms || !NXEqualColor(gParms->color, parms.color))
		NXSetColor(parms.color);

	if (gParms)
		*gParms = parms;

	return self;
}

/* Public routines. */
- setPathType:(int) value
{
	parms.path_type = (unsigned char) value;

	return self;
}

- (int)pathType
{
	return  (int)parms.path_type;
}

- setLineWidth:(float) value
{
	parms.linewidth = value;

	return self;
}

- (float)lineWidth
{
	return parms.linewidth;
}

- setLineJoin:(int) value
{
	parms.linejoin = (unsigned char) value;

	return self;
}

- (int)lineJoin
{
	return (int) parms.linejoin;
}

- setLineCap:(int) value
{
	parms.linecap = (unsigned char) value;

	return self;
}

- (int)lineCap
{
	return (int) parms.linecap;
}

- setMiterLimit:(float) value
{
	parms.miterlimit = value;

	return self;
}

- (float) miterLimit
{
	return parms.miterlimit;
}

- (float)gray
{
	float		value;

	NXConvertColorToGray(parms.color, &value);

	return value;
}

- setGray:(float) aGray
{
	parms.color = NXConvertGrayToColor(aGray);

	return self;
}

- (NXColor) color;
{
	return parms.color;
}

- setColor:(NXColor)aColor
{
	parms.color = aColor;

	return self;
}

/*
*	Returns the user path description for the user path. If a
*	rectangle is passed in then the user path is returned only
*	if it lies within the rectangle.
*/
- getUpath:(UPath **) aUpath  forRect:(NXRect *) r
{
	if (!r || NXIntersectsRect(r, &bounds))
		*aUpath = &path;
	else
		*aUpath = NULL;
	
	return self;
}

/*
 * Draws the graphic.
 */
- drawObject:(NXRect *) r  currentParms:(GParms *) gParms
	withManner:(int) manner  timingInfo:(Timing *) timing
{
	int		path_type;
	
	if (!r || NXIntersectsRect(r, &bounds))
	{
		timing->num_subpaths++;
		if (parms.path_type == FILL)
		{
			timing->num_fills++;
			path_type = dps_ufill;
		}
		else
		{
			timing->num_strokes++;
			path_type = dps_ustroke;
		}		
		
		[self setPSState:gParms];
		if (manner == REDBOOK)
		{
			makeRedBook(&path);
			if (parms.path_type == FILL)
				PSfill();
			else
				PSstroke();
		}
		else
		{
			if (manner == UCACHE)
				DPSDoUserPath(&path.pts[4], path.num_pts-4, dps_float,
					&path.ops[0], path.num_ops, path.pts, path_type);
			else
				DPSDoUserPath(&path.pts[4], path.num_pts-4, dps_float,
				&path.ops[1], path.num_ops-1, path.pts, path_type);
		}
	}

	return self;
}

@end

